package user

// 定义接口及接口对象
import (
	"context"
	"fmt"

	"golang.org/x/crypto/bcrypt"
)

const (
	AppName = "user"
)

// 定义user的功能
type Service interface {
	// 创建用户
	CreateUser(context.Context, *CreateUserRequest) (*User, error)
	// 删除用户
	DeleteUser(context.Context, *DeleteUserRequest) error
	// 用户查询
	DescirbeUser(context.Context, *DescirbeUserRequest) (*User, error)
}

func NewCreateUserRequest() *CreateUserRequest {
	return &CreateUserRequest{
		Role:  ROLE_AUTHOR,
		Label: map[string]string{},
	}
}

// 定义用户传递的数据
type CreateUserRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
	// 后面的中间件鉴权时，会用到Role
	Role Role `json:"role"`
	// 对象标签, Dep:部门A
	// Label字段不是结构化数据，无法直接存入到数据库中，所以要序列化json格式
	// 在以json格式，存入到数据库中
	Label    map[string]string `json:"label" gorm:"serializer:json"`
	isHashed bool
}

// 扩展 CreateUser函数中的校验用户参数时 的一个方法
func (c *CreateUserRequest) Validate() error {
	if c.Username == "" || c.Password == "" {
		return fmt.Errorf("请填写用户名或密码")
	}
	return nil
}

// 对传入的密码做加密处理
func (c *CreateUserRequest) PasswordHash() {
	if c.isHashed {
		return
	}

	b, _ := bcrypt.GenerateFromPassword([]byte(c.Password), bcrypt.DefaultCost)
	c.Password = string(b)
	c.isHashed = true
}

type DeleteUserRequest struct {
	Id int `json:"id"`
}

// 把DeleteUserRequest对象中的字段做类型转换，int-->string
func (d *DeleteUserRequest) IdString() string {
	return fmt.Sprintf("%d", d.Id)
}

// 可以通过id和username来查询，所以可以定义枚举
type DescirbeUserRequest struct {
	DescribeBy    DescribeBy `json:"describe_by"`
	DescribeValue string     `json:"describe_value"`
}

// 构造通过id查询用户的实例
func NewDescribeUserRequestById(id string) *DescirbeUserRequest {
	return &DescirbeUserRequest{
		// 没写DescribeBy，默认就是0
		DescribeValue: id,
	}
}

// 构造通过ussername查询用户的实例
func NewDescribeUserRequestByUsername(username string) *DescirbeUserRequest {
	return &DescirbeUserRequest{
		DescribeBy:    DESCRIBE_BY_USERNAME,
		DescribeValue: username,
	}
}
